import md5
import MySQLdb
import _mysql

db_connection = MySQLdb.connect(
    host='localhost', user='', passwd='', db='phpbb3')

def _PHPBB_hash_encode64(input, count, magic_string):
  """Copy the function _hash_encode64 in functions.php"""
  out = ''
  i = 0

  while True:
    value = ord(input[i])
    i += 1
    out += magic_string[value & 0x3f]

    if (i < count):
      value |= ord(input[i]) << 8

    out += magic_string[(value >> 6) & 0x3f]

    if (i >= count):
      break

    i += 1

    if (i < count):
      value |= ord(input[i]) << 16

    out += magic_string[(value >> 12) & 0x3f];

    if (i >= count):
      break

    i += 1

    out += magic_string[(value >> 18) & 0x3f];

    if (i >= count):
      break

  return out

def _PHPBB_hash_crypt_private(password, hash):
  """Copy the function _hash_crypt_private in functions.php"""
  out = '*'

  magic_string = ('./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                  'abcdefghijklmnopqrstuvwxyz')

  if not hash.startswith('$H$'):
    return out

  count_log2 = magic_string.index(hash[3])

  if count_log2 < 7 or count_log2 > 30:
    return out

  count = 1 << count_log2

  salt = hash[4:12]

  if len(salt) != 8:
    return out

  hash_out = md5.new(salt + password).digest()
  for i in range(count):
    hash_out = md5.new(hash_out + password).digest()

  return hash[0:12] + _PHPBB_hash_encode64(hash_out, 16, magic_string)

def check_phpbb_account(username, password):
  """Check if the given username and password are valid.

  If it is valid, return their username with the official capitalization, or
  return None if it is invalid.
  """
  cursor = db_connection.cursor()
  query = ('select username, user_password from phpbb_users '
           'where lower(username) = lower("%s")' %
           _mysql.escape_string(username))
  cursor.execute(query)
  result = cursor.fetchone()
  if not result:
    # Invalid username
    return None

  db_user, db_pass = result

  if len(db_pass) == 34:
    # New (phpbb3) style hash
    if _PHPBB_hash_crypt_private(password, db_pass) == db_pass:
      return db_user
  else:
    # Old style simple md5
    if md5.new(password).hexdigest() == db_pass:
      return db_user
